using B.S.NewMedical.Api.Write.Application.Command.Doctor;
using B.S.NewMedical.Domain.Appointment;
using B.S.NewMedical.ErrorCode;
using B.S.NewMedical.Infrastructure;
using B.S.NewMedical.Infrastructure.Interface;
using MediatR;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;

namespace B.S.NewMedical.Api.Write.Application.Handler.Doctor
{
    /// <summary>
    /// 医疗卡充值处理器
    /// </summary>
    public class RechargeCardHandler : IRequestHandler<RechargeCardCommand, ApiResult<RechargeResultDto>>
    {
        private readonly IBaseRepository<MedicalCard> _medicalCardRepository;
        private readonly MyDbcontext _dbContext;
        private readonly ILogger<RechargeCardHandler> _logger;

        public RechargeCardHandler(
            IBaseRepository<MedicalCard> medicalCardRepository,
            MyDbcontext dbContext,
            ILogger<RechargeCardHandler> logger)
        {
            _medicalCardRepository = medicalCardRepository;
            _dbContext = dbContext;
            _logger = logger;
        }

        public async Task<ApiResult<RechargeResultDto>> Handle(RechargeCardCommand request, CancellationToken cancellationToken)
        {
            using var transaction = await _dbContext.Database.BeginTransactionAsync(cancellationToken);
            try
            {
                _logger.LogInformation("开始处理医疗卡充值，卡号: {CardNo}，充值金额: {Amount}", request.CardNo, request.Amount);

                // 参数验证
                if (string.IsNullOrWhiteSpace(request.CardNo))
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "就诊卡号不能为空" };

                if (request.Amount <= 0)
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "充值金额必须大于0" };

                if (request.Amount > 10000)
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "单次充值金额不能超过10000元" };

                if (string.IsNullOrWhiteSpace(request.PayChannel))
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "支付方式不能为空" };

                if (request.OperatorId <= 0)
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "操作员ID不能为空" };

                // 查找医疗卡
                var medicalCard = await _medicalCardRepository.GetAll()
                    .FirstOrDefaultAsync(mc => mc.Card_no == request.CardNo && !mc.IsDeleted, cancellationToken);

                if (medicalCard == null)
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "就诊卡不存在" };

                if (medicalCard.Status != "正常")
                    return new ApiResult<RechargeResultDto> { Code = ApiEnum.Fail, Msg = "就诊卡状态异常，无法充值" };

                // 记录充值前余额
                var beforeBalance = medicalCard.Card_price;

                // 充值
                medicalCard.Card_price += request.Amount;
                await _medicalCardRepository.UpdateAsync(medicalCard);

                await _dbContext.SaveChangesAsync(cancellationToken);
                await transaction.CommitAsync(cancellationToken);

                var rechargeTime = DateTime.Now;
                var result = new RechargeResultDto
                {
                    BeforeBalance = beforeBalance,
                    RechargeAmount = request.Amount,
                    AfterBalance = medicalCard.Card_price,
                    RechargeTime = rechargeTime
                };

                _logger.LogInformation("医疗卡充值成功，卡号: {CardNo}，充值前余额: {BeforeBalance}，充值金额: {Amount}，充值后余额: {AfterBalance}",
                    request.CardNo, beforeBalance, request.Amount, medicalCard.Card_price);

                return new ApiResult<RechargeResultDto>
                {
                    Code = ApiEnum.Success,
                    Msg = "充值成功",
                    Data = result
                };
            }
            catch (Exception ex)
            {
                await transaction.RollbackAsync(cancellationToken);
                _logger.LogError(ex, "医疗卡充值时发生错误，卡号: {CardNo}", request.CardNo);
                return new ApiResult<RechargeResultDto>
                {
                    Code = ApiEnum.Fail,
                    Msg = "充值失败"
                };
            }
        }
    }
} 